#pragma once

#include "Thread.hpp"
#include "LockGuard.hpp"
#include <vector>
#include <queue>
#include <pthread.h>
using namespace YzcThread;

const int gnum = 5;

template <class T>
class ThreadPool;

template <class T>
class ThreadData
{
public:
    ThreadData(ThreadPool<T> *tp, const std::string &n)
        : threadpool(tp), name(n) {}

public:
    ThreadPool<T> *threadpool;
    std::string name;
};

template <class T>
class ThreadPool
{
private:
    static void *handlerTask(void *args)
    {
        ThreadData<T> *td = static_cast<ThreadData<T> *>(args);

        while (true)
        {
            // 读取任务队列，需要加锁
            // td->threadpool->lockQueue();
            T t;
            {
                // 通过花括号让LockGuard在获取任务后就销毁释放锁
                LockGuard lockguard(td->threadpool->mutex());
                while (td->threadpool->isQueueEmpty())
                {
                    td->threadpool->threadWait();
                }
                // 处理任务，处理任务的时候需不需要加锁？
                // T t = td->threadpool->pop(); // pop是将任务从公共队列中，拿到自己的独立栈中运行
                t = td->threadpool->pop();
            }

            // td->threadpool->unlockQueue();
            //  所以，运行任务不需要加锁
            std::cout << td->name << " 获取任务:" << t.toString() << " 并处理完成，结果是 " << t() << std::endl;
        }
        delete td;
        return nullptr;
    }

public:
    void lockQueue() { pthread_mutex_lock(&_mutex); }
    void unlockQueue() { pthread_mutex_unlock(&_mutex); }
    bool isQueueEmpty() { return _task_queue.empty(); }
    void threadWait() { pthread_cond_wait(&_cond, &_mutex); }
    T pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }

    pthread_mutex_t *mutex()
    {
        return &_mutex;
    }

public:
    ThreadPool(int num = gnum) : _num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);

        for (int i = 0; i < num; i++)
        {
            _threads.emplace_back(new Thread());
        }
    }

    // 让线程开始运行处理任务
    void run()
    {
        for (const auto &thread : _threads)
        {
            ThreadData<T> *td = new ThreadData<T>(this, thread->threadname());
            thread->start(handlerTask, td); // 通过start将this传递给handlerTask
            std::cout << thread->threadname() << " start ... " << std::endl;
        }
    }

    // 让其他线程向当前任务队列中放任务
    void push(const T &in)
    {
        // 使用lockguard加锁
        LockGuard lockguard(&_mutex);
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (const auto &thread : _threads)
            delete thread;
    }

private:
    int _num;                       // 线程数量
    std::vector<Thread *> _threads; // 线程组
    std::queue<T> _task_queue;      // 线程执行的任务队列，为共享资源，注意加锁
    pthread_mutex_t _mutex;         // 互斥锁
    pthread_cond_t _cond;           // 条件变量
};